# -*- coding: utf-8 -*-
from django.contrib.auth.hashers import make_password
from django.db.models import F
from rest_framework.decorators import action
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView

from apis.system.serializers import DictionarySerializer, UserSerializer, UserCreateSerializer, UserUpdateSerializer, \
    LoginSerializer, RoleSerializer, RoleCreateUpdateSerializer, MenuSerializer, MenuCreateSerializer, \
    WebRouterSerializer, MenuButtonSerializer, MenuButtonCreateUpdateSerializer, OperationLogSerializer, \
    MenuPermissonSerializer, ReportRecordUploadSerializer, DeptSerializer
from common.models.system import Dictionary, Users, Role, Menu, MenuButton, OperationLog, Dept
from utils import dispatch
from utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
from utils.viewset import CustomModelViewSet


class DeptViewSet(CustomModelViewSet):
    queryset = Dept.objects.all()
    serializer_class = DeptSerializer
    permission_classes_map = {
        'select': [IsAuthenticated],
        'no_level1_select': [IsAuthenticated],
    }

    def select(self, request):
        # queryset = self.filter_queryset(self.get_queryset()).values(value=F('id'), label=F('name'))
        queryset = self.get_queryset().values(value=F('id'), label=F('name'))
        return DetailResponse(data=queryset)

    def no_level1_select(self, request):
        # queryset = self.filter_queryset(self.get_queryset()).values(value=F('id'), label=F('name'))
        queryset = self.get_queryset().exclude(level='1').values(value=F('id'), label=F('name'))
        return DetailResponse(data=queryset)


class DictionaryViewSet(CustomModelViewSet):
    queryset = Dictionary.objects.all()
    serializer_class = DictionarySerializer
    extra_filter_backends = []
    search_fields = ['label']
    permission_classes_map = {
        'list': [IsAuthenticated]
    }


class UploadView(APIView):
    parser_classes = (MultiPartParser, FormParser)

    # permission_classes = []

    def post(self, request):
        serializer = ReportRecordUploadSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return DetailResponse(data=serializer.data)


class MenuViewSet(CustomModelViewSet):
    queryset = Menu.objects.all()
    serializer_class = MenuSerializer
    create_serializer_class = MenuCreateSerializer
    update_serializer_class = MenuCreateSerializer
    search_fields = ['name', 'status']
    filter_fields = {
        'parent': ['exact'],
        'name': ['icontains'],
        'status': ['exact'],
        'is_link': ['exact'],
        'visible': ['exact'],
        'cache': ['exact'],
        'is_catalog': ['exact']
    }
    extra_filter_backends = []

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def web_router(self, request):
        """用于进入系统前获取用户菜单"""
        user = request.user
        # 超管返回全部
        queryset = self.queryset.filter(status=True)
        if not user.is_superuser:
            menu_ids = user.role.values_list('menu__id', flat=True)
            queryset = queryset.filter(id__in=menu_ids)
            # TODO 优化序列化
            menus = WebRouterSerializer(queryset, many=True, request=request).data
        else:
            menus = WebRouterSerializer(queryset, many=True, request=request).data

        menu_ids = [i.get('id') for i in menus]
        for menu in menus:
            if menu['parent'] not in menu_ids:
                menu['parent'] = None
        menu_tree = self.menu_tree(menus)
        return DetailResponse(data={'router': menus, 'tree': menu_tree}, msg='获取成功')

    def list(self, request, *args, **kwargs):
        """懒加载"""
        params = request.query_params
        parent = params.get('parent', None)

        queryset = self.filter_queryset(self.get_queryset())
        if params:
            if parent:
                queryset = queryset.filter(parent=parent)
        else:
            queryset = queryset.filter(parent__isnull=True)
        serializer = MenuSerializer(queryset, many=True, request=request)
        data = serializer.data
        return DetailResponse(data=data)

    def menu_tree(self, source, parent=None):
        tree = []
        for item in source:
            if item.get('parent') == parent and not item.get('is_catalog'):
                # 是子节点  但不是目录，append
                # item['flag'] = True
                tree.append(item)
            elif item.get('parent') == parent and item.get('is_catalog'):
                # 是子节点，并且是目录，
                # item['flag'] = True
                item['children'] = self.menu_tree(source, item.get('id'))
                tree.append(item)

        # if parent is None:
        #     for i in source:
        #         if not i.get('flag') and i['visible']:
        #             tree.append(i)
        #         if i.get('children') and len(i.get('children')) == 0:
        #             del i['children']
        tree.sort(key=lambda x: x['sort'])
        return tree


class MenuButtonViewSet(CustomModelViewSet):
    queryset = MenuButton.objects.all()
    serializer_class = MenuButtonSerializer
    create_serializer_class = MenuButtonCreateUpdateSerializer
    update_serializer_class = MenuButtonCreateUpdateSerializer
    extra_filter_backends = []


class OperationLogViewSet(CustomModelViewSet):
    queryset = OperationLog.objects.all()
    serializer_class = OperationLogSerializer

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        if not request.user.is_superuser:
            queryset = queryset.filter(creator_id=request.user.id)

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True, request=request)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True, request=request)
        return SuccessResponse(data=serializer.data, msg='获取成功')


class RoleViewSet(CustomModelViewSet):
    queryset = Role.objects.all()
    serializer_class = RoleSerializer
    create_serializer_class = RoleCreateUpdateSerializer
    update_serializer_class = RoleCreateUpdateSerializer
    search_fields = {
        'name': ['icontains'],
        'type': ['exact']
    }

    def list(self, request, *args, **kwargs):
        """懒加载"""
        params = request.query_params
        parent = params.get('parent', None)

        queryset = self.filter_queryset(self.get_queryset())
        if not request.user.is_superuser:
            queryset = queryset.filter(creator_id=request.user.id)
        if params:
            if parent:
                queryset = queryset.filter(parent=parent)
            else:
                queryset = queryset.filter()
        else:
            queryset = queryset.filter(parent__isnull=True)
        serializer = RoleSerializer(queryset, many=True, request=request)
        data = serializer.data
        return DetailResponse(data=data)

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def data_scope(self, request):
        is_superuser = request.user.is_superuser
        role_queryset = Role.objects.filter(users__id=request.user.id).values_list('data_range', flat=True)
        if is_superuser:
            data = [
                {
                    "value": 0,
                    "label": '仅本人数据权限'
                },
                {
                    "value": 1,
                    "label": '本部门及以下数据权限'
                },
                {
                    "value": 2,
                    "label": '自定义数据权限'
                },
                {
                    "value": 3,
                    "label": '全部数据权限'
                },
                {
                    "value": 4,
                    "label": '本部门数据权限'
                }
            ]
        else:
            data = []
            data_range_list = list(set(role_queryset))
            for item in data_range_list:
                if item == 0:
                    data = [{
                        "value": 0,
                        "label": '仅本人数据权限'
                    }]
                elif item == 1:
                    data = [{
                        "value": 0,
                        "label": '仅本人数据权限'
                    }, {
                        "value": 1,
                        "label": '本部门及以下数据权限'
                    },
                        {
                            "value": 2,
                            "label": '本部门数据权限'
                        }]
                elif item == 2:
                    data = [{
                        "value": 0,
                        "label": '仅本人数据权限'
                    },
                        {
                            "value": 2,
                            "label": '本部门数据权限'
                        }]
                elif item == 3:
                    data = [{
                        "value": 0,
                        "label": '仅本人数据权限'
                    },
                        {
                            "value": 3,
                            "label": '全部数据权限'
                        }, ]
                elif item == 4:
                    data = [{
                        "value": 0,
                        "label": '仅本人数据权限'
                    },
                        {
                            "value": 4,
                            "label": '自定义数据权限'
                        }]
                else:
                    data = []
        return DetailResponse(data=data)

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def data_scope_dept(self, request):
        """根据当前角色获取自定义权限数据"""
        is_superuser = request.user.is_superuser
        role_list = request.user.role.values_list('data_range', flat=True)
        data_scope_list = list(set(role_list))  # 权限范围列表
        if is_superuser or 3 in data_scope_list:
            queryset = Dept.objects.values('id', 'name')
        else:
            enterprise_list = request.user.role.values_list('dept', flat=True)
            queryset = Dept.objects.filter(id__in=enterprise_list).values('id', 'name')
        return DetailResponse(data=queryset)

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def role_get_menu(self, request):
        """根据当前用户的角色返回角色拥有的菜单，权限配置用"""
        user = request.user
        # 超管返回全部
        queryset = Menu.objects.filter(status=True, visible=True)
        if not user.is_superuser:
            # 管理角色可查看该平台所有菜单
            menu_ids = user.role.values_list('menu__id', flat=True)
            queryset = queryset.filter(id__in=menu_ids)
            menus = MenuPermissonSerializer(queryset, many=True, request=request).data
        else:
            menus = MenuPermissonSerializer(queryset, many=True, request=request).data
        return DetailResponse(data=menus, msg='获取成功')

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def select(self, request):
        """角色下拉菜单"""
        params = request.query_params
        parent = params.get('parent', None)
        type_ = params.get('type', None)

        if request.user.is_superuser:
            queryset = self.queryset
        else:
            queryset = self.queryset.filter(creator_id=request.user.id)
        if params:
            if parent:
                queryset = queryset.filter(parent=parent)
            else:
                queryset = queryset.filter()
        else:
            queryset = queryset.filter(parent__isnull=True)
        if type_ and type_ == '1':
            queryset = queryset.filter(type=type_)
        elif type_ and type_ == '2':
            queryset = self.queryset.filter(type=type_)
        data = queryset.values(value=F('id'), label=F('name'))
        return DetailResponse(data=data)


class UserViewSet(CustomModelViewSet):
    """用户接口"""
    queryset = Users.objects.filter(is_active=True).exclude(is_superuser=1).all()
    serializer_class = UserSerializer
    create_serializer_class = UserCreateSerializer
    update_serializer_class = UserUpdateSerializer
    filter_fields = {
        'name': ['icontains'],
        'mobile': ['icontains'],
        'username': ['icontains'],
        'is_active': ['exact'],
        'type': ['exact'],
        'dept_id': ['exact'],
    }
    search_fields = ['username', 'name']

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def select(self, request):
        params = request.query_params
        dept_id = params.get('dept_id', -1)
        # queryset = self.filter_queryset(self.get_queryset()).values(value=F('id'), label=F('name'))

        if dept_id != -1:
            queryset = self.get_queryset().filter(dept_id=dept_id).values(value=F('id'), label=F('name'))
        else:
            queryset = self.get_queryset().values(value=F('id'), label=F('name'))
        return DetailResponse(data=queryset)

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        queryset = queryset.exclude(pk=request.user.id)

        if not request.user.is_superuser:
            queryset = queryset.filter(creator_id=request.user.id)
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True, request=request)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(queryset, many=True, request=request)
        return SuccessResponse(data=serializer.data, msg='获取成功')

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def user_info(self, request):
        """获取当前用户信息"""
        user = request.user
        result = {
            'id': user.id,
            'username': user.username,
            'name': user.name,
            'mobile': user.mobile,
            'avatar': user.avatar,
            'is_superuser': user.is_superuser,
            'dept_id': user.dept_id,
            'roles': user.role.values('id', 'name'),
        }
        return DetailResponse(data=result, msg='获取成功')

    @action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
    def change_password(self, request, *args, **kwargs):
        """修改密码"""
        data = request.data
        old_pwd = data.get('old_password')
        new_pwd1 = data.get('new_password1')
        new_pwd2 = data.get('new_password2')
        if old_pwd is None or new_pwd1 is None or new_pwd2 is None:
            return ErrorResponse(msg='参数不能为空')
        if new_pwd1 != new_pwd2:
            return ErrorResponse(msg='两次密码不匹配')
        if request.user.check_password(old_pwd):
            request.user.password = make_password(new_pwd1)
            request.user.save()
            return DetailResponse(data=None, msg='修改成功')
        else:
            return ErrorResponse(msg='旧密码不正确')

    @action(methods=['PUT'], detail=True)
    def reset_password(self, request, pk):
        """密码重置"""
        instance = Users.objects.filter(id=pk).first()
        data = request.data
        new_pwd1 = data.get('new_password1')
        new_pwd2 = data.get('new_password2')
        if instance:
            if new_pwd1 != new_pwd2:
                return ErrorResponse(msg='两次密码不匹配')
            else:
                instance.password = make_password(new_pwd1)
                instance.save()
                return DetailResponse(data=None, msg='修改成功')
        else:
            return ErrorResponse(msg='未获取到用户')

    def update_info(self, request, *args, **kwargs):
        avatar = request.data.get('avatar')
        name = request.data.get('name')
        partial = kwargs.pop('partial', True)
        instance = self.request.user
        data = {'avatar': avatar or instance.avatar, 'name': name or instance.name}
        serializer = self.get_serializer(instance, data=data, request=request, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return DetailResponse(data=serializer.data, msg='更新成功')


class LoginView(TokenObtainPairView):
    """登录接口"""

    serializer_class = LoginSerializer
    permission_classes = []


class LogoutView(APIView):
    def post(self, request):
        return DetailResponse(msg='注销成功')


class InitDictionaryViewSet(APIView):
    """获取初始化配置"""
    authentication_classes = []
    permission_classes = []
    queryset = Dictionary.objects.all()

    def get(self, request):
        dictionary_key = self.request.query_params.get('dictionary_key')
        if dictionary_key:
            if dictionary_key == 'all':
                data = [ele for ele in dispatch.get_dictionary_config().values()]
                if not data:
                    dispatch.refresh_dictionary()
                    data = [ele for ele in dispatch.get_dictionary_config().values()]
            else:
                data = self.queryset.filter(parent__value=dictionary_key, status=True) \
                    .values('label', 'value', 'type', 'color')
            return DetailResponse(data=data, msg='获取成功')
        return DetailResponse(data=[], msg='获取成功')
